package cn.yqx.bankshop.oauth2.config;

import cn.yqx.bankshop.constants.FromLoginConstant;
import cn.yqx.bankshop.oauth2.authentication.code.ImageCodeValidateFilter;
import cn.yqx.bankshop.oauth2.authentication.mobile.SmsCodeAuthenticationSecurityConfig;
import cn.yqx.bankshop.oauth2.authentication.mobile.SmsCodeFilter;
import cn.yqx.bankshop.oauth2.handle.CustomAuthenticationSuccessHandler;
import cn.yqx.bankshop.oauth2.handle.CustomizeAuthenticationFailureHandler;

import cn.yqx.bankshop.oauth2.properties.SecurityProperties;
import cn.yqx.bankshop.oauth2.service.impl.CustomUserDetailsService;
import cn.yqx.bankshop.oauth2.store.VcodeManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;


import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import javax.sql.DataSource;


@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final int TOKEN_VALIDITY_SECONDS = 60*60*24*7 ;
    private static final String SMS_CODE_URL = "/code/sms" ;
    private static final String USER_AUTH_URL = "/api/v1/user-auth" ;
    private static final String IMAGE_CODE_URL =  "/code/image" ;
    private static final String MY_LOGOUT = "/myLogout" ;

    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;
    @Autowired
    CustomUserDetailsService userDetailsService ;
    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private VcodeManager vcodeManager;
    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
    @Autowired
    private CustomizeAuthenticationFailureHandler customizeAuthenticationFailureHandler ;

    @Autowired
    private ImageCodeValidateFilter imageCodeValidateFilter;

    /**
     * 配置用户信息
     */

    public void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.userDetailsService(userDetailsService);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Autowired
    DataSource dataSource ;

    @Bean
    public JdbcTokenRepositoryImpl jdbcTokenRepository(){

        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl() ;
        jdbcTokenRepository.setDataSource(dataSource);
        //jdbcTokenRepository.setCreateTableOnStartup(true);

        return jdbcTokenRepository ;
    }
    public void configure(HttpSecurity http) throws Exception {

        SmsCodeFilter smsCodeFilter = new SmsCodeFilter(vcodeManager);
        smsCodeFilter.setSecurityProperties(securityProperties);
        smsCodeFilter.afterPropertiesSet();


        http.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(imageCodeValidateFilter,UsernamePasswordAuthenticationFilter.class)
                //表单登录,loginPage为登录请求的url,loginProcessingUrl为表单登录处理的URL
                .formLogin()
                //.loginPage(FromLoginConstant.LOGIN_PAGE)
                .loginProcessingUrl(FromLoginConstant.LOGIN_PROCESSING_URL)
                //登录成功之后的处理
                .failureHandler(customizeAuthenticationFailureHandler)
                .successHandler(customAuthenticationSuccessHandler)
                //允许访问
                .and().authorizeRequests().antMatchers(
                FromLoginConstant.LOGIN_PROCESSING_URL,
                FromLoginConstant.LOGIN_PAGE,
                securityProperties.getOauthLogin().getOauthLogin(),
                securityProperties.getOauthLogin().getOauthGrant(),
                MY_LOGOUT,
                SMS_CODE_URL,
                USER_AUTH_URL,
                IMAGE_CODE_URL)
                .permitAll().anyRequest().authenticated()
                //禁用跨站伪造
                .and().csrf().disable()
                .rememberMe()
                .tokenRepository(jdbcTokenRepository())
                .tokenValiditySeconds(TOKEN_VALIDITY_SECONDS)
                .and()
                //短信验证码配置
                .apply(smsCodeAuthenticationSecurityConfig);


    }
}
